"""
查询清理模块

提供查询文本的清理和标准化功能。
"""

import re
from typing import Optional, List, Dict, Any


class QueryCleaner:
    """
    查询清理器

    负责查询文本的清理、标准化和格式化。
    提供多种清理策略，支持中英文混合查询。
    """

    def __init__(self, config: Optional[Dict[str, Any]] = None):
        """
        初始化查询清理器

        Args:
            config: 清理配置，可包含自定义规则
        """
        self.config = config or {}
        self._setup_cleaning_rules()

    def _setup_cleaning_rules(self) -> None:
        """设置清理规则"""
        # 需要保留的字符（中英文、数字、基本标点）
        self.allowed_pattern = r'[\w\s\u4e00-\u9fff，。！？；：""''（）【】《》\-+]'

        # 空白字符标准化
        self.whitespace_pattern = r'\s+'

        # 特殊字符模式（需要清理的）
        self.special_chars_pattern = r'[^\w\s\u4e00-\u9fff，。！？；：""''（）【】《》]'

        # URL模式（可选择保留或清理）
        self.url_pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'

        # 邮箱模式
        self.email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'

    def clean_query(
        self,
        query: str,
        options: Optional[Dict[str, Any]] = None
    ) -> str:
        """
        清理查询文本

        Args:
            query: 原始查询文本
            options: 清理选项
                - remove_urls: 是否移除URL (默认False)
                - remove_emails: 是否移除邮箱 (默认False)
                - preserve_case: 是否保留大小写 (默认True)
                - normalize_whitespace: 是否标准化空白字符 (默认True)

        Returns:
            str: 清理后的查询文本
        """
        if not query:
            return ""

        # 设置默认选项
        clean_options = {
            'remove_urls': False,
            'remove_emails': False,
            'preserve_case': True,
            'normalize_whitespace': True,
            'remove_special_chars': True,
            'preserve_numbers': True,
            'preserve_chinese': True
        }
        clean_options.update(options or {})

        cleaned = query

        # 处理URL
        if clean_options['remove_urls']:
            cleaned = re.sub(self.url_pattern, '', cleaned)

        # 处理邮箱
        if clean_options['remove_emails']:
            cleaned = re.sub(self.email_pattern, '', cleaned)

        # 标准化空白字符
        if clean_options['normalize_whitespace']:
            cleaned = re.sub(self.whitespace_pattern, ' ', cleaned.strip())

        # 移除特殊字符
        if clean_options['remove_special_chars']:
            cleaned = self._remove_special_characters(cleaned)

        # 大小写处理
        if not clean_options['preserve_case']:
            cleaned = cleaned.lower()

        # 最终清理
        cleaned = cleaned.strip()

        return cleaned

    def _remove_special_characters(self, text: str) -> str:
        """
        移除特殊字符，保留基本标点和中英文

        Args:
            text: 输入文本

        Returns:
            str: 清理后的文本
        """
        # 保留中英文、数字、空格和基本标点
        cleaned = re.sub(self.special_chars_pattern, '', text)
        return cleaned

    def normalize_query(self, query: str) -> str:
        """
        标准化查询文本

        包括统一标点符号、处理全角半角字符等。

        Args:
            query: 原始查询

        Returns:
            str: 标准化后的查询
        """
        if not query:
            return ""

        # 全角转半角
        normalized = self._convert_fullwidth_to_halfwidth(query)

        # 统一标点符号
        normalized = self._normalize_punctuation(normalized)

        # 标准化空白字符
        normalized = re.sub(r'\s+', ' ', normalized.strip())

        return normalized

    def _convert_fullwidth_to_halfwidth(self, text: str) -> str:
        """全角字符转半角字符"""
        # 全角字符映射表
        fullwidth_to_halfwidth = {
            '０': '0', '１': '1', '２': '2', '３': '3', '４': '4',
            '５': '5', '６': '6', '７': '7', '８': '8', '９': '9',
            'Ａ': 'A', 'Ｂ': 'B', 'Ｃ': 'C', 'Ｄ': 'D', 'Ｅ': 'E',
            'Ｆ': 'F', 'Ｇ': 'G', 'Ｈ': 'H', 'Ｉ': 'I', 'Ｊ': 'J',
            'Ｋ': 'K', 'Ｌ': 'L', 'Ｍ': 'M', 'Ｎ': 'N', 'Ｏ': 'O',
            'Ｐ': 'P', 'Ｑ': 'Q', 'Ｒ': 'R', 'Ｓ': 'S', 'Ｔ': 'T',
            'Ｕ': 'U', 'Ｖ': 'V', 'Ｗ': 'W', 'Ｘ': 'X', 'Ｙ': 'Y',
            'Ｚ': 'Z', 'ａ': 'a', 'ｂ': 'b', 'ｃ': 'c', 'ｄ': 'd',
            'ｅ': 'e', 'ｆ': 'f', 'ｇ': 'g', 'ｈ': 'h', 'ｉ': 'i',
            'ｊ': 'j', 'ｋ': 'k', 'ｌ': 'l', 'ｍ': 'm', 'ｎ': 'n',
            'ｏ': 'o', 'ｐ': 'p', 'ｑ': 'q', 'ｒ': 'r', 'ｓ': 's',
            'ｔ': 't', 'ｕ': 'u', 'ｖ': 'v', 'ｗ': 'w', 'ｘ': 'x',
            'ｙ': 'y', 'ｚ': 'z'
        }

        result = []
        for char in text:
            result.append(fullwidth_to_halfwidth.get(char, char))

        return ''.join(result)

    def _normalize_punctuation(self, text: str) -> str:
        """统一标点符号"""
        # 中文标点映射到统一格式
        punctuation_map = {
            '，': ',',  # 逗号统一为半角
            '。': '.',  # 句号统一为半角
            '！': '!',  # 感叹号统一为半角
            '？': '?',  # 问号统一为半角
            '；': ';',  # 分号统一为半角
            '：': ':',  # 冒号统一为半角
            '"': '"',   # 双引号统一
            '"': '"',
            ''': "'",   # 单引号统一
            ''': "'",
            '（': '(',  # 括号统一为半角
            '）': ')',
            '【': '[',  # 方括号统一
            '】': ']'
        }

        for fullwidth, halfwidth in punctuation_map.items():
            text = text.replace(fullwidth, halfwidth)

        return text

    def validate_query(self, query: str) -> Dict[str, Any]:
        """
        验证查询文本

        Args:
            query: 查询文本

        Returns:
            Dict[str, Any]: 验证结果
        """
        if not query:
            return {
                "is_valid": False,
                "issues": ["查询为空"],
                "cleaned_query": ""
            }

        issues = []
        cleaned = self.clean_query(query)

        # 检查长度
        if len(cleaned) < 2:
            issues.append("查询过短")
        elif len(cleaned) > 1000:
            issues.append("查询过长")

        # 检查是否包含有效字符
        if not re.search(r'[a-zA-Z\u4e00-\u9fff]', cleaned):
            issues.append("查询缺少有效内容")

        # 检查是否主要是标点符号
        punctuation_ratio = len(re.sub(r'[a-zA-Z0-9\u4e00-\u9fff\s]', '', cleaned)) / len(cleaned) if cleaned else 0
        if punctuation_ratio > 0.5:
            issues.append("查询包含过多标点符号")

        is_valid = len(issues) == 0

        return {
            "is_valid": is_valid,
            "issues": issues,
            "cleaned_query": cleaned,
            "original_length": len(query),
            "cleaned_length": len(cleaned),
            "reduction_ratio": (len(query) - len(cleaned)) / len(query) if query else 0
        }

    def batch_clean(
        self,
        queries: List[str],
        options: Optional[Dict[str, Any]] = None
    ) -> List[Dict[str, Any]]:
        """
        批量清理查询

        Args:
            queries: 查询列表
            options: 清理选项

        Returns:
            List[Dict[str, Any]]: 清理结果列表
        """
        results = []

        for i, query in enumerate(queries):
            try:
                cleaned = self.clean_query(query, options)
                validation = self.validate_query(cleaned)

                result = {
                    "index": i,
                    "original_query": query,
                    "cleaned_query": cleaned,
                    "is_valid": validation["is_valid"],
                    "issues": validation["issues"],
                    "original_length": len(query),
                    "cleaned_length": len(cleaned)
                }

                results.append(result)

            except Exception as e:
                results.append({
                    "index": i,
                    "original_query": query,
                    "cleaned_query": query,
                    "is_valid": False,
                    "issues": [f"清理失败: {str(e)}"],
                    "original_length": len(query),
                    "cleaned_length": len(query)
                })

        return results

    def get_cleaning_stats(self, queries: List[str]) -> Dict[str, Any]:
        """
        获取清理统计信息

        Args:
            queries: 查询列表

        Returns:
            Dict[str, Any]: 统计信息
        """
        if not queries:
            return {
                "total_queries": 0,
                "avg_original_length": 0,
                "avg_cleaned_length": 0,
                "total_reduction": 0,
                "valid_queries": 0,
                "invalid_queries": 0
            }

        batch_results = self.batch_clean(queries)

        total_original = sum(r["original_length"] for r in batch_results)
        total_cleaned = sum(r["cleaned_length"] for r in batch_results)
        total_reduction = sum(r["original_length"] - r["cleaned_length"] for r in batch_results)
        valid_count = sum(1 for r in batch_results if r["is_valid"])
        invalid_count = len(batch_results) - valid_count

        return {
            "total_queries": len(queries),
            "avg_original_length": round(total_original / len(queries), 1),
            "avg_cleaned_length": round(total_cleaned / len(queries), 1),
            "total_reduction": total_reduction,
            "avg_reduction": round(total_reduction / len(queries), 1),
            "reduction_ratio": round(total_reduction / total_original, 3) if total_original > 0 else 0,
            "valid_queries": valid_count,
            "invalid_queries": invalid_count,
            "validity_rate": round(valid_count / len(queries), 3)
        }

    def __str__(self) -> str:
        """返回清理器信息的字符串表示"""
        return f"""
=== 查询清理器 ===
支持功能: 文本清理、标准化、验证、批量处理
处理语言: 中文、英文、混合
默认选项: 移除特殊字符、保留大小写、标准化空白
        """.strip()